package com.jahe.learn.nio;

import com.sun.org.apache.bcel.internal.generic.Select;

import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.Set;

/**
 * 开了 5 个端口，一个Selector线程 监听多个端口的ServerSocketChannel的连接事件。
 * @author: jahe.lai
 * @create: 2019-12-25 11:27
 */
public class MultiPortServertSocketDemo {

   static int[] ports = new int[5];

   static {
       ports[0] = 5000;
       ports[1] = 5001;
       ports[2] = 5002;
       ports[3] = 5003;
       ports[4] = 5004;
   }

    public static void main(String[] args) throws Exception {
        Selector selector = Selector.open();

        for (int i=0; i < ports.length; ++i) {
            ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
            serverSocketChannel.configureBlocking(false);
            ServerSocket serverSocket = serverSocketChannel.socket();
            InetSocketAddress address = new InetSocketAddress(ports[i]);
            serverSocket.bind(address);
            // 注册，实现通道与选择器的关联关系
            // SelectionKey是一个token，代表了一个channel注册到一个Selector上的关系。
            SelectionKey selectionKey = serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
            System.out.println("正在监听端口：" + ports[i]);
        }

        while (true) {
            int keyNumbers = selector.select();
            System.out.println("keyNumbers：" + keyNumbers);

            Set<SelectionKey> selectionKeys = selector.selectedKeys();
            System.out.println("selectionKeys：" + selectionKeys);
            Iterator<SelectionKey> keyIterator = selectionKeys.iterator();
            while (keyIterator.hasNext()) {
                SelectionKey key = keyIterator.next();
                if (key.isAcceptable()) {
                    // 正在监听连接的channel
                    ServerSocketChannel ssChannel = (ServerSocketChannel)key.channel();
                    // 新建立连接的channel
                    SocketChannel socketChannel = ssChannel.accept();
                    // 将新连接的channel设置为非阻塞
                    socketChannel.configureBlocking(false);

                    // 注册到selector 上，并添加关注的事件。
                    socketChannel.register(selector, SelectionKey.OP_READ);
                    keyIterator.remove();
                    System.out.println("获得客户端连接：" + socketChannel);
                } else if (key.isReadable()) {
                    SocketChannel socketChannel = (SocketChannel)key.channel();
                    int bytesRead = 0;
                    ByteBuffer buffer = ByteBuffer.allocate(512);
                    buffer.clear();
                    while (true) {
                        int r = socketChannel.read(buffer);
                        bytesRead += r;
                        if (r <= 0) {
                            break;
                        }
                        buffer.flip();
                        socketChannel.write(buffer);
                    }
                    keyIterator.remove();
//                    buffer.flip();
//                    System.out.println("读取到的数据：" + new String(buffer.array())
//                            + ", 来自于：" + socketChannel);
                }
            }
        }
    }

}
